#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>

#include <unistd.h>

#include <string>
#include <iostream>
#include <functional>

#include "Client.hpp"
#include "protocol.hpp"
#include "Calculate.hpp"
#include "Comm.hpp"
#include "margins.hpp"

#define BUFFERSIZE 1024

using task_t = std::function<void(Socket*)>;

void Function(Socket* sk)
{
    //建筑一个工厂
    std::unique_ptr<Factory> factory = std::make_unique<Factory>();
    //种随机数种子
    srand(time(nullptr)); 
    char opers[] = "+-*/%";

    while (true)
    {
        sleep(1);

        //1. 加载数据
        int data_x = rand() % 5;
        int data_y = rand() % 5;
        char oper = opers[rand() % strlen(opers)];
        printf("%d %c %d = ?\n", data_x, oper, data_y);
        //2. 构建结构化数据
        std::shared_ptr<Request> req = factory->BuildRequest(data_x, data_y, oper);
        // 3. 序列化
        std::string message = req->Serialize();
        // 4. 添加报文边界
        AddMargins(message);
        // 5. 发送
        sk->Send(message);
        // 6. 接收处理数据
        std::string datagram;
        std::string new_datagram;
        sk->Recv(new_datagram);
        datagram = new_datagram;
        // 7. 去掉报文边界
        // 若操作失败，则表明，没有完整的报文
        if(!DelMargins(new_datagram, datagram)) continue;
        // 8. 反序列化
        auto resp = factory->BuildResponse();
        resp->Deserialize(new_datagram);
        //打印结果
        printf("%d %c %d = %d[%d]\n", data_x, oper, data_y, resp->GetResult(), resp->GetStat());        
    }
    close(sk->GetSockfd());
}

int main(int argc, const char *argv[])
{
    if (argc != 3)
    {
        printf("Usage:\n\t%s server_ip server_port\n\n", argv[0]);
        exit(0);
    }

    std::string server_ip = argv[1];
    in_port_t server_port = std::stoi(argv[2]);
    std::unique_ptr<Client<task_t>>client = std::make_unique<Client<task_t>>(server_ip, server_port, std::bind(Function, std::placeholders::_1));
    client->Running();

    return 0;
}